package com.hzw.saas.web.im.im;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Slf4j
@Order(1)
@Component
public class SaasImServer implements Runnable {
    public static final int PORT = 8082;
    public static final String PATH = "/chat";

    @Resource(name = "channelInitializer")
    private ChannelHandler channelInitializer;

    private ServerBootstrap bootstrap; //启动器
    private EventLoopGroup bossGroup; //boss loop 接受连接进来的进程
    private EventLoopGroup workerGroup; //处理业务
    private ChannelFuture serverChannelFuture;

    public void run() {
        this.build();
    }

    /**
     * 启动Netty Websocket服务器
     */
    public void build() {
        try {
            bootstrap = new ServerBootstrap();
            bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
            bossGroup = new NioEventLoopGroup();
            workerGroup = new NioEventLoopGroup(5); //不输入参数默认单线程维护
            bootstrap.group(bossGroup, workerGroup)  //设置接受线程和业务处理线程
                .channel(NioServerSocketChannel.class) //设置channel处理方式
                .childHandler(channelInitializer);
            serverChannelFuture = bootstrap.bind(PORT).sync();
            log.info("SAAS-IM Websocket服务器启动完成已绑定端口: {}", PORT);
        } catch (Exception e) {
            log.info(e.getMessage());
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            e.printStackTrace();
        }
    }

    /**
     * 关闭连接
     */
    public void close(){
        serverChannelFuture.channel().close();
        Future<?> bossGroupFuture = bossGroup.shutdownGracefully();
        Future<?> workerGroupFuture = workerGroup.shutdownGracefully();

        try {
            bossGroupFuture.await();
            workerGroupFuture.await();
        } catch (InterruptedException ignore) {
            ignore.printStackTrace();
        }
    }

}
